
package org.xteam.pascal.parser.ast;

public class PascalAstPrinter extends DefaultPascalVisitor {

	private java.io.PrintStream out;
	private int indentLevel;
	
	public PascalAstPrinter(java.io.PrintStream out) {
		this.out = out;
		indentLevel = 0;
	}
	
	public void visitProgram(Program aProgram) {
		out.print("Program(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aProgram.getName() != null) {
			aProgram.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("arguments=");
		if (aProgram.getArguments() != null) {
			out.println("[");
			++indentLevel;
			for (Identifier e : aProgram.getArguments()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("body=");
		if (aProgram.getBody() != null) {
			aProgram.getBody().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitBlock(Block aBlock) {
		out.print("Block(");
		++indentLevel;out.println();
		printIndent();
		out.print("labels=");
		if (aBlock.getLabels() != null) {
			out.println("[");
			++indentLevel;
			for (IntegerValue e : aBlock.getLabels()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("constants=");
		if (aBlock.getConstants() != null) {
			out.println("[");
			++indentLevel;
			for (ConstantDefinition e : aBlock.getConstants()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("types=");
		if (aBlock.getTypes() != null) {
			out.println("[");
			++indentLevel;
			for (TypeDefinition e : aBlock.getTypes()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("variables=");
		if (aBlock.getVariables() != null) {
			out.println("[");
			++indentLevel;
			for (VariableDeclaration e : aBlock.getVariables()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("functions=");
		if (aBlock.getFunctions() != null) {
			out.println("[");
			++indentLevel;
			for (FunctionDefinition e : aBlock.getFunctions()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statements=");
		if (aBlock.getStatements() != null) {
			out.println("[");
			++indentLevel;
			for (Statement e : aBlock.getStatements()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitConstantDefinition(ConstantDefinition aConstantDefinition) {
		out.print("ConstantDefinition(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aConstantDefinition.getName() != null) {
			aConstantDefinition.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("value=");
		if (aConstantDefinition.getValue() != null) {
			aConstantDefinition.getValue().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitTypeDefinition(TypeDefinition aTypeDefinition) {
		out.print("TypeDefinition(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aTypeDefinition.getName() != null) {
			aTypeDefinition.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("value=");
		if (aTypeDefinition.getValue() != null) {
			aTypeDefinition.getValue().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitVariableDeclaration(VariableDeclaration aVariableDeclaration) {
		out.print("VariableDeclaration(");
		++indentLevel;out.println();
		printIndent();
		out.print("names=");
		if (aVariableDeclaration.getNames() != null) {
			out.println("[");
			++indentLevel;
			for (Identifier e : aVariableDeclaration.getNames()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aVariableDeclaration.getType() != null) {
			aVariableDeclaration.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitProcedure(Procedure aProcedure) {
		out.print("Procedure(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aProcedure.getName() != null) {
			aProcedure.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("parameters=");
		if (aProcedure.getParameters() != null) {
			out.println("[");
			++indentLevel;
			for (Parameter e : aProcedure.getParameters()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("body=");
		if (aProcedure.getBody() != null) {
			aProcedure.getBody().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFunction(Function aFunction) {
		out.print("Function(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aFunction.getName() != null) {
			aFunction.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("parameters=");
		if (aFunction.getParameters() != null) {
			out.println("[");
			++indentLevel;
			for (Parameter e : aFunction.getParameters()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("returnType=");
		if (aFunction.getReturnType() != null) {
			aFunction.getReturnType().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("body=");
		if (aFunction.getBody() != null) {
			aFunction.getBody().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitVariableParameter(VariableParameter aVariableParameter) {
		out.print("VariableParameter(");
		++indentLevel;out.println();
		printIndent();
		out.print("flag=");
		if (aVariableParameter.getFlag() != null) {
			aVariableParameter.getFlag().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("names=");
		if (aVariableParameter.getNames() != null) {
			out.println("[");
			++indentLevel;
			for (Identifier e : aVariableParameter.getNames()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aVariableParameter.getType() != null) {
			aVariableParameter.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitProcedureParameter(ProcedureParameter aProcedureParameter) {
		out.print("ProcedureParameter(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aProcedureParameter.getName() != null) {
			aProcedureParameter.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("parameters=");
		if (aProcedureParameter.getParameters() != null) {
			out.println("[");
			++indentLevel;
			for (Parameter e : aProcedureParameter.getParameters()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFunctionParameter(FunctionParameter aFunctionParameter) {
		out.print("FunctionParameter(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aFunctionParameter.getName() != null) {
			aFunctionParameter.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("parameters=");
		if (aFunctionParameter.getParameters() != null) {
			out.println("[");
			++indentLevel;
			for (Parameter e : aFunctionParameter.getParameters()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("returnType=");
		if (aFunctionParameter.getReturnType() != null) {
			aFunctionParameter.getReturnType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitVarFlag(VarFlag aVarFlag) {
		out.print("VarFlag(");
		out.println(")");
	}
	
	public void visitReferenceType(ReferenceType aReferenceType) {
		out.print("ReferenceType(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aReferenceType.getName() != null) {
			aReferenceType.getName().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitArraySchemaType(ArraySchemaType aArraySchemaType) {
		out.print("ArraySchemaType(");
		++indentLevel;out.println();
		printIndent();
		out.print("ranges=");
		if (aArraySchemaType.getRanges() != null) {
			out.println("[");
			++indentLevel;
			for (Range e : aArraySchemaType.getRanges()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aArraySchemaType.getType() != null) {
			aArraySchemaType.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitPackedArraySchemaType(PackedArraySchemaType aPackedArraySchemaType) {
		out.print("PackedArraySchemaType(");
		++indentLevel;out.println();
		printIndent();
		out.print("range=");
		if (aPackedArraySchemaType.getRange() != null) {
			aPackedArraySchemaType.getRange().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aPackedArraySchemaType.getType() != null) {
			aPackedArraySchemaType.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitRange(Range aRange) {
		out.print("Range(");
		++indentLevel;out.println();
		printIndent();
		out.print("from=");
		if (aRange.getFrom() != null) {
			aRange.getFrom().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("to=");
		if (aRange.getTo() != null) {
			aRange.getTo().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("step=");
		if (aRange.getStep() != null) {
			aRange.getStep().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitTypeReference(TypeReference aTypeReference) {
		out.print("TypeReference(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aTypeReference.getName() != null) {
			aTypeReference.getName().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitEnumType(EnumType aEnumType) {
		out.print("EnumType(");
		++indentLevel;out.println();
		printIndent();
		out.print("names=");
		if (aEnumType.getNames() != null) {
			out.println("[");
			++indentLevel;
			for (Identifier e : aEnumType.getNames()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitRangeType(RangeType aRangeType) {
		out.print("RangeType(");
		++indentLevel;out.println();
		printIndent();
		out.print("from=");
		if (aRangeType.getFrom() != null) {
			aRangeType.getFrom().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("to=");
		if (aRangeType.getTo() != null) {
			aRangeType.getTo().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitPointerType(PointerType aPointerType) {
		out.print("PointerType(");
		++indentLevel;out.println();
		printIndent();
		out.print("type=");
		if (aPointerType.getType() != null) {
			aPointerType.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitArrayType(ArrayType aArrayType) {
		out.print("ArrayType(");
		++indentLevel;out.println();
		printIndent();
		out.print("flag=");
		if (aArrayType.getFlag() != null) {
			aArrayType.getFlag().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aArrayType.getType() != null) {
			aArrayType.getType().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("indexes=");
		if (aArrayType.getIndexes() != null) {
			out.println("[");
			++indentLevel;
			for (Type e : aArrayType.getIndexes()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitRecordType(RecordType aRecordType) {
		out.print("RecordType(");
		++indentLevel;out.println();
		printIndent();
		out.print("flag=");
		if (aRecordType.getFlag() != null) {
			aRecordType.getFlag().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("body=");
		if (aRecordType.getBody() != null) {
			aRecordType.getBody().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFieldsAndVariant(FieldsAndVariant aFieldsAndVariant) {
		out.print("FieldsAndVariant(");
		++indentLevel;out.println();
		printIndent();
		out.print("fields=");
		if (aFieldsAndVariant.getFields() != null) {
			out.println("[");
			++indentLevel;
			for (Field e : aFieldsAndVariant.getFields()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("variant=");
		if (aFieldsAndVariant.getVariant() != null) {
			aFieldsAndVariant.getVariant().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitRecordCase(RecordCase aRecordCase) {
		out.print("RecordCase(");
		++indentLevel;out.println();
		printIndent();
		out.print("selector=");
		if (aRecordCase.getSelector() != null) {
			aRecordCase.getSelector().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("arms=");
		if (aRecordCase.getArms() != null) {
			out.println("[");
			++indentLevel;
			for (RecordCaseArm e : aRecordCase.getArms()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitVariantSelector(VariantSelector aVariantSelector) {
		out.print("VariantSelector(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aVariantSelector.getName() != null) {
			aVariantSelector.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aVariantSelector.getType() != null) {
			aVariantSelector.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitRecordCaseArm(RecordCaseArm aRecordCaseArm) {
		out.print("RecordCaseArm(");
		++indentLevel;out.println();
		printIndent();
		out.print("values=");
		if (aRecordCaseArm.getValues() != null) {
			out.println("[");
			++indentLevel;
			for (Expression e : aRecordCaseArm.getValues()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("body=");
		if (aRecordCaseArm.getBody() != null) {
			aRecordCaseArm.getBody().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitField(Field aField) {
		out.print("Field(");
		++indentLevel;out.println();
		printIndent();
		out.print("names=");
		if (aField.getNames() != null) {
			out.println("[");
			++indentLevel;
			for (Identifier e : aField.getNames()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aField.getType() != null) {
			aField.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitSetType(SetType aSetType) {
		out.print("SetType(");
		++indentLevel;out.println();
		printIndent();
		out.print("flag=");
		if (aSetType.getFlag() != null) {
			aSetType.getFlag().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aSetType.getType() != null) {
			aSetType.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFileType(FileType aFileType) {
		out.print("FileType(");
		++indentLevel;out.println();
		printIndent();
		out.print("flag=");
		if (aFileType.getFlag() != null) {
			aFileType.getFlag().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("type=");
		if (aFileType.getType() != null) {
			aFileType.getType().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitPackedFlag(PackedFlag aPackedFlag) {
		out.print("PackedFlag(");
		out.println(")");
	}
	
	public void visitEmptyStatement(EmptyStatement aEmptyStatement) {
		out.print("EmptyStatement(");
		out.println(")");
	}
	
	public void visitLabelStatement(LabelStatement aLabelStatement) {
		out.print("LabelStatement(");
		++indentLevel;out.println();
		printIndent();
		out.print("label=");
		if (aLabelStatement.getLabel() != null) {
			aLabelStatement.getLabel().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statement=");
		if (aLabelStatement.getStatement() != null) {
			aLabelStatement.getStatement().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitAssignment(Assignment aAssignment) {
		out.print("Assignment(");
		++indentLevel;out.println();
		printIndent();
		out.print("variable=");
		if (aAssignment.getVariable() != null) {
			aAssignment.getVariable().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("expression=");
		if (aAssignment.getExpression() != null) {
			aAssignment.getExpression().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFunctionCall(FunctionCall aFunctionCall) {
		out.print("FunctionCall(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aFunctionCall.getName() != null) {
			aFunctionCall.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("parameters=");
		if (aFunctionCall.getParameters() != null) {
			out.println("[");
			++indentLevel;
			for (Expression e : aFunctionCall.getParameters()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitGoto(Goto aGoto) {
		out.print("Goto(");
		++indentLevel;out.println();
		printIndent();
		out.print("label=");
		if (aGoto.getLabel() != null) {
			aGoto.getLabel().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitCompound(Compound aCompound) {
		out.print("Compound(");
		++indentLevel;out.println();
		printIndent();
		out.print("statements=");
		if (aCompound.getStatements() != null) {
			out.println("[");
			++indentLevel;
			for (Statement e : aCompound.getStatements()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitIf(If aIf) {
		out.print("If(");
		++indentLevel;out.println();
		printIndent();
		out.print("condition=");
		if (aIf.getCondition() != null) {
			aIf.getCondition().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("thenStatement=");
		if (aIf.getThenStatement() != null) {
			aIf.getThenStatement().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("elseStatement=");
		if (aIf.getElseStatement() != null) {
			aIf.getElseStatement().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitCase(Case aCase) {
		out.print("Case(");
		++indentLevel;out.println();
		printIndent();
		out.print("condition=");
		if (aCase.getCondition() != null) {
			aCase.getCondition().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("arms=");
		if (aCase.getArms() != null) {
			out.println("[");
			++indentLevel;
			for (CaseArm e : aCase.getArms()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitCaseArm(CaseArm aCaseArm) {
		out.print("CaseArm(");
		++indentLevel;out.println();
		printIndent();
		out.print("constants=");
		if (aCaseArm.getConstants() != null) {
			out.println("[");
			++indentLevel;
			for (Expression e : aCaseArm.getConstants()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statement=");
		if (aCaseArm.getStatement() != null) {
			aCaseArm.getStatement().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitRepeatUntil(RepeatUntil aRepeatUntil) {
		out.print("RepeatUntil(");
		++indentLevel;out.println();
		printIndent();
		out.print("condition=");
		if (aRepeatUntil.getCondition() != null) {
			aRepeatUntil.getCondition().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statements=");
		if (aRepeatUntil.getStatements() != null) {
			out.println("[");
			++indentLevel;
			for (Statement e : aRepeatUntil.getStatements()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitWhile(While aWhile) {
		out.print("While(");
		++indentLevel;out.println();
		printIndent();
		out.print("condition=");
		if (aWhile.getCondition() != null) {
			aWhile.getCondition().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statement=");
		if (aWhile.getStatement() != null) {
			aWhile.getStatement().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFor(For aFor) {
		out.print("For(");
		++indentLevel;out.println();
		printIndent();
		out.print("variable=");
		if (aFor.getVariable() != null) {
			aFor.getVariable().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("from=");
		if (aFor.getFrom() != null) {
			aFor.getFrom().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("to=");
		if (aFor.getTo() != null) {
			aFor.getTo().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("dir=");
		if (aFor.getDir() != null) {
			aFor.getDir().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statement=");
		if (aFor.getStatement() != null) {
			aFor.getStatement().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitWith(With aWith) {
		out.print("With(");
		++indentLevel;out.println();
		printIndent();
		out.print("variables=");
		if (aWith.getVariables() != null) {
			out.println("[");
			++indentLevel;
			for (Access e : aWith.getVariables()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		printIndent();
		out.print("statement=");
		if (aWith.getStatement() != null) {
			aWith.getStatement().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitUpFlag(UpFlag aUpFlag) {
		out.print("UpFlag(");
		out.println(")");
	}
	
	public void visitDownFlag(DownFlag aDownFlag) {
		out.print("DownFlag(");
		out.println(")");
	}
	
	public void visitVariableAccess(VariableAccess aVariableAccess) {
		out.print("VariableAccess(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aVariableAccess.getName() != null) {
			aVariableAccess.getName().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitArrayAccess(ArrayAccess aArrayAccess) {
		out.print("ArrayAccess(");
		++indentLevel;out.println();
		printIndent();
		out.print("expression=");
		if (aArrayAccess.getExpression() != null) {
			aArrayAccess.getExpression().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("indexes=");
		if (aArrayAccess.getIndexes() != null) {
			out.println("[");
			++indentLevel;
			for (Expression e : aArrayAccess.getIndexes()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFieldAccess(FieldAccess aFieldAccess) {
		out.print("FieldAccess(");
		++indentLevel;out.println();
		printIndent();
		out.print("expression=");
		if (aFieldAccess.getExpression() != null) {
			aFieldAccess.getExpression().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("name=");
		if (aFieldAccess.getName() != null) {
			aFieldAccess.getName().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitPointerAccess(PointerAccess aPointerAccess) {
		out.print("PointerAccess(");
		++indentLevel;out.println();
		printIndent();
		out.print("expression=");
		if (aPointerAccess.getExpression() != null) {
			aPointerAccess.getExpression().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitEqualsExpression(EqualsExpression aEqualsExpression) {
		out.print("EqualsExpression(");
		out.println(")");
	}
	
	public void visitNotEqualsExpression(NotEqualsExpression aNotEqualsExpression) {
		out.print("NotEqualsExpression(");
		out.println(")");
	}
	
	public void visitLowerThanExpression(LowerThanExpression aLowerThanExpression) {
		out.print("LowerThanExpression(");
		out.println(")");
	}
	
	public void visitGreaterThanExpression(GreaterThanExpression aGreaterThanExpression) {
		out.print("GreaterThanExpression(");
		out.println(")");
	}
	
	public void visitLowerOrEqualsExpression(LowerOrEqualsExpression aLowerOrEqualsExpression) {
		out.print("LowerOrEqualsExpression(");
		out.println(")");
	}
	
	public void visitGreaterOrEqualsExpression(GreaterOrEqualsExpression aGreaterOrEqualsExpression) {
		out.print("GreaterOrEqualsExpression(");
		out.println(")");
	}
	
	public void visitInExpression(InExpression aInExpression) {
		out.print("InExpression(");
		out.println(")");
	}
	
	public void visitAddExpression(AddExpression aAddExpression) {
		out.print("AddExpression(");
		out.println(")");
	}
	
	public void visitSubExpression(SubExpression aSubExpression) {
		out.print("SubExpression(");
		out.println(")");
	}
	
	public void visitOrExpression(OrExpression aOrExpression) {
		out.print("OrExpression(");
		out.println(")");
	}
	
	public void visitMulExpression(MulExpression aMulExpression) {
		out.print("MulExpression(");
		out.println(")");
	}
	
	public void visitDivExpression(DivExpression aDivExpression) {
		out.print("DivExpression(");
		out.println(")");
	}
	
	public void visitIntegralDivExpression(IntegralDivExpression aIntegralDivExpression) {
		out.print("IntegralDivExpression(");
		out.println(")");
	}
	
	public void visitModuloExpression(ModuloExpression aModuloExpression) {
		out.print("ModuloExpression(");
		out.println(")");
	}
	
	public void visitAndExpression(AndExpression aAndExpression) {
		out.print("AndExpression(");
		out.println(")");
	}
	
	public void visitNegateExpression(NegateExpression aNegateExpression) {
		out.print("NegateExpression(");
		++indentLevel;out.println();
		printIndent();
		out.print("expression=");
		if (aNegateExpression.getExpression() != null) {
			aNegateExpression.getExpression().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitNotExpression(NotExpression aNotExpression) {
		out.print("NotExpression(");
		++indentLevel;out.println();
		printIndent();
		out.print("expression=");
		if (aNotExpression.getExpression() != null) {
			aNotExpression.getExpression().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitFormatExpression(FormatExpression aFormatExpression) {
		out.print("FormatExpression(");
		++indentLevel;out.println();
		printIndent();
		out.print("expr=");
		if (aFormatExpression.getExpr() != null) {
			aFormatExpression.getExpr().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("width=");
		if (aFormatExpression.getWidth() != null) {
			aFormatExpression.getWidth().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("to=");
		if (aFormatExpression.getTo() != null) {
			aFormatExpression.getTo().visit(this);
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitIdentifierExpression(IdentifierExpression aIdentifierExpression) {
		out.print("IdentifierExpression(");
		out.print("value=");
		if (aIdentifierExpression.getValue() != null) {
			out.print(aIdentifierExpression.getValue());
		} else {
			out.print("null");
		}
		out.println(")");
	}
	
	public void visitStringExpression(StringExpression aStringExpression) {
		out.print("StringExpression(");
		out.print("value=");
		if (aStringExpression.getValue() != null) {
			out.print(aStringExpression.getValue());
		} else {
			out.print("null");
		}
		out.println(")");
	}
	
	public void visitNumberExpression(NumberExpression aNumberExpression) {
		out.print("NumberExpression(");
		out.print("value=");
		if (aNumberExpression.getValue() != null) {
			out.print(aNumberExpression.getValue());
		} else {
			out.print("null");
		}
		out.println(")");
	}
	
	public void visitIntegerExpression(IntegerExpression aIntegerExpression) {
		out.print("IntegerExpression(");
		out.print("value=");
		if (aIntegerExpression.getValue() != null) {
			out.print(aIntegerExpression.getValue());
		} else {
			out.print("null");
		}
		out.println(")");
	}
	
	public void visitNilExpression(NilExpression aNilExpression) {
		out.print("NilExpression(");
		out.println(")");
	}
	
	public void visitFuncallExpression(FuncallExpression aFuncallExpression) {
		out.print("FuncallExpression(");
		++indentLevel;out.println();
		printIndent();
		out.print("name=");
		if (aFuncallExpression.getName() != null) {
			aFuncallExpression.getName().visit(this);
		} else {
			out.println("null");
		}
		printIndent();
		out.print("arguments=");
		if (aFuncallExpression.getArguments() != null) {
			out.println("[");
			++indentLevel;
			for (Expression e : aFuncallExpression.getArguments()) {
				printIndent();
				e.visit(this);
			}
			--indentLevel;
			printIndent();
			out.println("]");
		} else {
			out.println("null");
		}
		--indentLevel;printIndent();
		out.println(")");
	}
	
	public void visitIdentifier(Identifier aIdentifier) {
		out.print("Identifier(");
		out.print("name=");
		if (aIdentifier.getName() != null) {
			out.print(aIdentifier.getName());
		} else {
			out.print("null");
		}
		out.println(")");
	}
	
	public void visitIntegerValue(IntegerValue aIntegerValue) {
		out.print("IntegerValue(");
		out.print("value=");
		if (aIntegerValue.getValue() != null) {
			out.print(aIntegerValue.getValue());
		} else {
			out.print("null");
		}
		out.println(")");
	}
	
	private void printIndent() {
		for (int i = 0; i < indentLevel; ++i) {
			out.print("  ");
		}
	}
}
